home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / OCLIEN.PAK / MAINVIEW.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  34KB  |  1,290 lines

  1. // mainview.cpp : implementation of the CMainView class
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1992-1995 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Microsoft Foundation Classes Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12.  
  13.  
  14. #include "stdafx.h"
  15. #include "oclient.h"
  16.  
  17. #include "maindoc.h"
  18. #include "mainview.h"
  19. #include "rectitem.h"
  20.  
  21. #ifdef _DEBUG
  22. #undef THIS_FILE
  23. static char BASED_CODE THIS_FILE[] = __FILE__;
  24. #endif
  25.  
  26. /////////////////////////////////////////////////////////////////////////////
  27. // CMainView
  28.  
  29. CBrush NEAR CMainView::m_brHatch;
  30. CLIPFORMAT CMainView::m_cfObjectDescriptor=NULL;
  31.  
  32. IMPLEMENT_DYNCREATE(CMainView, CScrollView)
  33.  
  34. BEGIN_MESSAGE_MAP(CMainView, CScrollView)
  35.     //{{AFX_MSG_MAP(CMainView)
  36.     ON_COMMAND(ID_EDIT_PASTE, OnPaste)
  37.     ON_COMMAND(ID_EDIT_PASTE_LINK, OnPasteLink)
  38.     ON_COMMAND(ID_OLE_INSERT_NEW, OnInsertObject)
  39.     ON_UPDATE_COMMAND_UI(ID_EDIT_CLEAR, OnUpdateEditMenu)
  40.     ON_COMMAND(ID_EDIT_CLEAR, OnEditClear)
  41.     ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
  42.     ON_COMMAND(ID_EDIT_CUT, OnEditCut)
  43.     ON_WM_LBUTTONDBLCLK()
  44.     ON_WM_LBUTTONDOWN()
  45.     ON_WM_SETCURSOR()
  46.     ON_WM_RBUTTONDOWN()
  47.     ON_WM_CHAR()
  48.     ON_WM_SETFOCUS()
  49.     ON_WM_CREATE()
  50.     ON_WM_SIZE()
  51.     ON_COMMAND(ID_OBJECT_DISPLAYCONTENT, OnObjectDisplayContent)
  52.     ON_UPDATE_COMMAND_UI(ID_OBJECT_DISPLAYCONTENT, OnUpdateObjectDisplayContent)
  53.     ON_COMMAND(ID_OBJECT_DISPLAYASICON, OnObjectDisplayAsIcon)
  54.     ON_UPDATE_COMMAND_UI(ID_OBJECT_DISPLAYASICON, OnUpdateObjectDisplayAsIcon)
  55.     ON_COMMAND(ID_EDIT_PASTE_SPECIAL, OnPasteSpecial)
  56.     ON_UPDATE_COMMAND_UI(ID_EDIT_CLONE, OnUpdateEditClone)
  57.     ON_COMMAND(ID_EDIT_CLONE, OnEditClone)
  58.     ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE_SPECIAL, OnUpdateEditPaste)
  59.     ON_COMMAND(ID_OBJECT_RESETSIZE, OnObjectResetsize)
  60.     ON_COMMAND(ID_CANCEL_INPLACE, OnCancelInplace)
  61.     ON_WM_DESTROY()
  62.     ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste)
  63.     ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditMenu)
  64.     ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditMenu)
  65.     ON_UPDATE_COMMAND_UI(ID_OBJECT_RESETSIZE, OnUpdateEditMenu)
  66.     ON_COMMAND(ID_OLE_CHANGE_SOURCE, OnOleChangeSource)
  67.     ON_UPDATE_COMMAND_UI(ID_OLE_CHANGE_SOURCE, OnUpdateOleChangeSource)
  68.     ON_COMMAND(ID_OLE_EDIT_PROPERTIES, OnOleEditProperties)
  69.     ON_UPDATE_COMMAND_UI(ID_OLE_EDIT_PROPERTIES, OnUpdateOleEditProperties)
  70.     //}}AFX_MSG_MAP
  71.     // Standard printing commands
  72.     ON_COMMAND(ID_FILE_PRINT, CScrollView::OnFilePrint)
  73.     ON_COMMAND(ID_FILE_PRINT_PREVIEW, CScrollView::OnFilePrintPreview)
  74. END_MESSAGE_MAP()
  75.  
  76. /////////////////////////////////////////////////////////////////////////////
  77. // CMainView construction/destruction
  78.  
  79. CMainView::CMainView()
  80. {
  81.     if (m_brHatch.m_hObject == NULL)
  82.         m_brHatch.CreateHatchBrush(HS_DIAGCROSS, RGB(0,0,0));
  83.     if (m_cfObjectDescriptor == NULL)
  84.         m_cfObjectDescriptor =
  85.             (CLIPFORMAT)::RegisterClipboardFormat(_T("Object Descriptor"));
  86.  
  87.     m_pSelection = NULL;
  88.     m_prevDropEffect = DROPEFFECT_NONE;
  89.     m_bInDrag = FALSE;
  90. }
  91.  
  92. CMainView::~CMainView()
  93. {
  94. }
  95.  
  96. void CMainView::OnInitialUpdate()
  97. {
  98.     CScrollView::OnInitialUpdate();
  99.  
  100.     // We can't pass MM_ANISOTROPIC to SetScrollSizes so we have to convert to MM_TEXT
  101.     CSize size = GetDocument()->GetDocumentSize();
  102.     CClientDC dc(NULL);
  103.     size.cx = MulDiv(size.cx, dc.GetDeviceCaps(LOGPIXELSX), 100);
  104.     size.cy = MulDiv(size.cy, dc.GetDeviceCaps(LOGPIXELSY), 100);
  105.     SetScrollSizes(MM_TEXT, size);
  106. }
  107.  
  108. /////////////////////////////////////////////////////////////////////////////
  109. // CMainView drawing
  110.  
  111. void CMainView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
  112. {
  113.     CScrollView::OnPrepareDC(pDC, pInfo);
  114.     // set up a reasonable default context
  115.     pDC->SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
  116.     pDC->SetBkColor(::GetSysColor(COLOR_WINDOW));
  117.  
  118.     // LOENGLISH units are based on physical inches
  119.     // We want logical inches so we have to do it differently
  120.     pDC->SetMapMode(MM_ANISOTROPIC);
  121.     pDC->SetViewportExt(
  122.         pDC->GetDeviceCaps(LOGPIXELSX), pDC->GetDeviceCaps(LOGPIXELSY));
  123.     pDC->SetWindowExt(100,-100);
  124. }
  125.  
  126. void CMainView::SetupTracker(CRectTracker* pTracker, CRectItem* pItem,
  127.     CRect* pTrueRect)
  128. {
  129.     ASSERT(pTracker != NULL);
  130.     ASSERT(pItem != NULL);
  131.  
  132.     pTracker->m_rect = pItem->GetRect();
  133.     DocToClient(pTracker->m_rect);
  134.  
  135.     // set minimum size for our OLE items
  136.     pTracker->m_sizeMin.cx = 8;
  137.     pTracker->m_sizeMin.cy = 8;
  138.  
  139.     pTracker->m_nStyle = 0;
  140.  
  141.     // setup resize handles if item is selected
  142.     if (pItem == m_pSelection)
  143.         pTracker->m_nStyle |= CRectTracker::resizeInside;
  144.  
  145.     // put correct border depending on item type
  146.     if (pItem->GetType() == OT_LINK)
  147.         pTracker->m_nStyle |= CRectTracker::dottedLine;
  148.     else
  149.         pTracker->m_nStyle |= CRectTracker::solidLine;
  150.  
  151.     // put hatching over the item if it is currently open
  152.     if (pItem->GetItemState() == COleClientItem::openState ||
  153.         pItem->GetItemState() == COleClientItem::activeUIState)
  154.     {
  155.         pTracker->m_nStyle |= CRectTracker::hatchInside;
  156.     }
  157.  
  158.     if (pTrueRect != NULL)
  159.         pTracker->GetTrueRect(pTrueRect);
  160. }
  161.  
  162. void CMainView::OnDraw(CDC* pDC)
  163. {
  164.     CMainDoc* pDoc = GetDocument();
  165.  
  166.     ASSERT_VALID(pDC);
  167.  
  168.     if (!pDC->IsPrinting())
  169.     {
  170.         m_brHatch.UnrealizeObject();
  171.         CPoint point(0, 0);
  172.         pDC->LPtoDP(&point);
  173.         pDC->SetBrushOrg(point.x % 8, point.y % 8);
  174.  
  175.         CRect rcClip;
  176.         GetClientRect(&rcClip);
  177.         ClientToDoc(rcClip);
  178.         CSize docSize = pDoc->GetDocumentSize();
  179.         if (rcClip.right > docSize.cx)
  180.         {
  181.             CRect rcFill(rcClip);
  182.             rcFill.left = max(rcFill.left,docSize.cx);
  183.             pDC->FillRect(rcFill,&m_brHatch);
  184.         }
  185.         if (rcClip.bottom < -docSize.cy)
  186.         {
  187.             CRect rcFill(rcClip);
  188.             rcFill.top = min(rcFill.top, -docSize.cy);
  189.             pDC->FillRect(rcFill,&m_brHatch);
  190.         }
  191.     }
  192.  
  193.     // Draw all the CRectItems
  194.     POSITION pos = pDoc->GetStartPosition();
  195.     while (pos != NULL)
  196.     {
  197.         CRectItem* pItem = DYNAMIC_DOWNCAST(CRectItem, pDoc->GetNextItem(pos));
  198.         if (pItem != NULL)
  199.         {
  200.             pItem->Draw(pDC, pItem->GetRect());
  201.  
  202.             if (!pDC->IsPrinting())
  203.             {
  204.                 // draw the tracker
  205.                 CRectTracker tracker;
  206.                 CRect rectTrue;
  207.                 SetupTracker(&tracker, pItem, &rectTrue);
  208.                 ClientToDoc(rectTrue);
  209.                 if (pDC->RectVisible(&rectTrue))
  210.                     tracker.Draw(pDC);
  211.             }
  212.         }
  213.     }
  214. }
  215.  
  216. // pHint is the deleted item or NULL if deselect/delete all
  217. void CMainView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
  218. {
  219.     if (pHint == NULL && lHint == 0)
  220.     {
  221.         // some sort of clear all
  222.         m_pSelection = NULL;
  223.     }
  224.  
  225.     if (pHint != NULL && pHint->IsKindOf(RUNTIME_CLASS(CRectItem)))
  226.     {
  227.         // just invalidate the one item
  228.         InvalidateItem((CRectItem*)pHint);
  229.  
  230.         // clear selection if pointing to deleted item
  231.         if (lHint == 1 && pHint == m_pSelection)
  232.         {
  233.             // specific case of pHint being deleted
  234.             m_pSelection = NULL;
  235.         }
  236.     }
  237.     else if (lHint != 0)
  238.     {
  239.         // invalidate arbitrary rectangle
  240.         InvalidateRect((CRect*)lHint);
  241.     }
  242.     else
  243.     {
  244.         // complete update
  245.         CScrollView::OnUpdate(pSender, lHint, pHint);
  246.     }
  247. }
  248.  
  249. void CMainView::InvalidateItem(CRectItem* pItem)
  250. {
  251.     if (m_nMapMode != 0)
  252.     {
  253.         CRectTracker tracker;
  254.         CRect rect;
  255.         SetupTracker(&tracker, pItem, &rect);
  256.         InvalidateRect(&rect);
  257.     }
  258. }
  259.  
  260. BOOL CMainView::OnScrollBy(CSize sizeScroll, BOOL bDoScroll)
  261. {
  262.     // remove drag/drop feedback before scrolling
  263.     if (bDoScroll && m_prevDropEffect != DROPEFFECT_NONE)
  264.     {
  265.         CClientDC dc(this);
  266.         dc.DrawFocusRect(CRect(m_dragPoint, m_dragSize));
  267.             // erase previous focus rect
  268.         m_prevDropEffect = DROPEFFECT_NONE;
  269.     }
  270.  
  271.     // do the scroll
  272.     if (!CScrollView::OnScrollBy(sizeScroll, bDoScroll))
  273.         return FALSE;
  274.  
  275.     // update the position of any in-place active item
  276.     if (bDoScroll)
  277.     {
  278.         UpdateActiveItem();
  279.         UpdateWindow();
  280.     }
  281.  
  282.     return TRUE;
  283. }
  284.  
  285. /////////////////////////////////////////////////////////////////////////////
  286. // CMainView printing
  287.  
  288. BOOL CMainView::OnPreparePrinting(CPrintInfo* pInfo)
  289. {
  290.     // default preparation
  291.     return DoPreparePrinting(pInfo);
  292. }
  293.  
  294. /////////////////////////////////////////////////////////////////////////////
  295. // Selection support
  296.  
  297. BOOL CMainView::IsSelected(const CObject* pDocItem) const
  298. {
  299.     return (pDocItem == m_pSelection);
  300. }
  301.  
  302. void CMainView::SetSelection(CRectItem* pNewSel, BOOL bSafeSelect)
  303. {
  304.     if (pNewSel != NULL && pNewSel == m_pSelection)
  305.         return;
  306.  
  307.     // deactivate any in-place active item on this view!
  308.     COleClientItem* pActiveItem = GetDocument()->GetInPlaceActiveItem(this);
  309.     if (pActiveItem != NULL && pNewSel != pActiveItem)
  310.     {
  311.         if (bSafeSelect)
  312.             return;
  313.         // if we found one, deactivate it
  314.         pActiveItem->Close();
  315.         ASSERT(GetDocument()->GetInPlaceActiveItem(this) == NULL);
  316.     }
  317.     if (m_pSelection != NULL) // invalidate the old item
  318.         InvalidateItem(m_pSelection);
  319.     if ((m_pSelection = pNewSel) != NULL) // invalidate the new item
  320.         InvalidateItem(m_pSelection);
  321. }
  322.  
  323. /////////////////////////////////////////////////////////////////////////////
  324. // CMainView diagnostics
  325.  
  326. #ifdef _DEBUG
  327. void CMainView::AssertValid() const
  328. {
  329.     CScrollView::AssertValid();
  330. }
  331.  
  332. void CMainView::Dump(CDumpContext& dc) const
  333. {
  334.     CScrollView::Dump(dc);
  335. }
  336.  
  337. #endif //_DEBUG
  338.  
  339. /////////////////////////////////////////////////////////////////////////////
  340. // Main 'Edit' menu commands
  341.  
  342. void CMainView::OnUpdateEditMenu(CCmdUI* pCmdUI)
  343. {
  344.     // most Edit menu commands are enabled only if we have a selection
  345.     //  and there are no in-place activations for this view
  346.     pCmdUI->Enable(m_pSelection != NULL &&
  347.         GetDocument()->GetInPlaceActiveItem(this) == NULL);
  348. }
  349.  
  350. void CMainView::OnEditCut()
  351. {
  352.     ASSERT(m_pSelection != NULL);
  353.     TRY
  354.     {
  355.         m_pSelection->CopyToClipboard(TRUE);
  356.         OnEditClear();
  357.     }
  358.     CATCH_ALL(e)
  359.     {
  360.         AfxMessageBox(IDP_CLIPBOARD_CUT_FAILED);
  361.     }
  362.     END_CATCH_ALL
  363. }
  364.  
  365. void CMainView::OnEditCopy()
  366. {
  367.     ASSERT(m_pSelection != NULL);
  368.     TRY
  369.     {
  370.         m_pSelection->CopyToClipboard(TRUE);
  371.     }
  372.     CATCH_ALL(e)
  373.     {
  374.         AfxMessageBox(IDP_CLIPBOARD_COPY_FAILED);
  375.     }
  376.     END_CATCH_ALL
  377. }
  378.  
  379. void CMainView::OnEditClear()
  380. {
  381.     if (m_pSelection != NULL)
  382.         GetDocument()->DeleteItem(m_pSelection);
  383. }
  384.  
  385. void CMainView::OnPaste()
  386. {
  387.     if (DoPasteItem(FALSE, NULL, NULL) == NULL)
  388.         AfxMessageBox(IDP_GET_FROM_CLIPBOARD_FAILED);
  389. }
  390.  
  391. void CMainView::OnPasteLink()
  392. {
  393.     if (DoPasteItem(TRUE, NULL, NULL) == NULL)
  394.         AfxMessageBox(IDP_GET_FROM_CLIPBOARD_FAILED);
  395. }
  396.  
  397. void CMainView::DoPasteNative(
  398.     COleDataObject* pDataObject, CPoint* pPoint, CRectItem* pItem)
  399. {
  400.     // get file refering to clipboard data
  401.     CFile* pFile = pDataObject->GetFileData(CMainDoc::m_cfPrivate);
  402.     if (pFile == NULL)
  403.         {
  404.         // if the file failed to open, throw an exception
  405.         // to force cleanup in DoPasteItem.  the exact
  406.         // type of exception thrown here is unimportant...
  407.         
  408.         AfxThrowFileException(CFileException::generic);
  409.         }
  410.  
  411.     CArchive ar(pFile, CArchive::load);
  412.     TRY
  413.     {
  414.         // connect the file to an archive and read the data
  415.         ar.m_pDocument = GetDocument(); // for COleClientItem serialize
  416.         pItem->Serialize(ar);
  417.     }
  418.     CATCH_ALL(e)
  419.     {
  420.         ar.Close();
  421.         delete pFile;
  422.         THROW_LAST();
  423.     }
  424.     END_CATCH_ALL
  425.  
  426.     ar.Close();
  427.     delete pFile;
  428.  
  429.     // adjust position to that specified by point
  430.     if (pPoint != NULL)
  431.         pItem->m_ptPos = *pPoint;
  432. }
  433.  
  434. void CMainView::DoPasteStandard(BOOL bLink, COleDataObject* pDataObject,
  435.     CPoint* pPoint, CRectItem* pItem, CLIPFORMAT cfFormat)
  436. {
  437.     if (bLink)      // paste link
  438.     {
  439.         if (!pItem->CreateLinkFromData(pDataObject))
  440.             AfxThrowMemoryException();  // any exception will do
  441.     }
  442.     // paste embedded
  443.     else if (!pItem->CreateFromData(pDataObject) &&
  444.         !pItem->CreateStaticFromData(pDataObject, OLERENDER_DRAW, cfFormat))
  445.     {
  446.         AfxThrowMemoryException();      // any exception will do
  447.     }
  448.  
  449.     // copy the current iconic representation
  450.     FORMATETC fmtetc;
  451.     fmtetc.cfFormat = CF_METAFILEPICT;
  452.     fmtetc.dwAspect = DVASPECT_ICON;
  453.     fmtetc.ptd = NULL;
  454.     fmtetc.tymed = TYMED_MFPICT;
  455.     fmtetc.lindex = 1;
  456.     HGLOBAL hObj = pDataObject->GetGlobalData(CF_METAFILEPICT, &fmtetc);
  457.     if (hObj != NULL)
  458.     {
  459.         pItem->SetIconicMetafile(hObj);
  460.         // the following code is an easy way to free a metafile pict
  461.         STGMEDIUM stgMed;
  462.         memset(&stgMed, 0, sizeof(stgMed));
  463.         stgMed.tymed = TYMED_MFPICT;
  464.         stgMed.hGlobal = hObj;
  465.         ReleaseStgMedium(&stgMed);
  466.     }
  467.  
  468.     // set the current drawing aspect
  469.     hObj = pDataObject->GetGlobalData(m_cfObjectDescriptor);
  470.     if (hObj != NULL)
  471.     {
  472.         ASSERT(hObj != NULL);
  473.         // got CF_OBJECTDESCRIPTOR ok.  Lock it down and extract size.
  474.         LPOBJECTDESCRIPTOR pObjDesc = (LPOBJECTDESCRIPTOR)GlobalLock(hObj);
  475.         ASSERT(pObjDesc != NULL);
  476.         pItem->SetDrawAspect((DVASPECT)pObjDesc->dwDrawAspect);
  477.         GlobalUnlock(hObj);
  478.         GlobalFree(hObj);
  479.     }
  480.  
  481.     // set top-left based on point of drop
  482.     if (pPoint != NULL)
  483.         pItem->m_ptPos = *pPoint;
  484.  
  485.     // get size from drag/drop operation
  486.     CSize size;
  487.     if (GetObjectInfo(pDataObject, &size, NULL) && size.cx != 0 && size.cy != 0)
  488.     {
  489.         // use size obtained from object instead of default
  490. #ifdef _MAC
  491.         size.cy = -size.cy;
  492. #else
  493.         size.cx = MulDiv(size.cx, 10, 254);
  494.         size.cy = -MulDiv(size.cy, 10, 254);
  495. #endif
  496.         pItem->SetSize(size);
  497.         CSize sizeExtent;
  498.         pItem->GetCachedExtent(&sizeExtent);
  499.         pItem->SetBaseSize(sizeExtent);
  500.     }
  501.     else
  502.     {
  503.         // no extent from CF_OBJECTDESCRIPTOR, use extent from object
  504.         pItem->UpdateExtent();
  505.     }
  506. }
  507.  
  508.  
  509. // Helper for paste/pastelink
  510. //
  511. //                  bLink       pDataObject     pPoint              cfFormat
  512. //  EditPaste       FALSE       NULL(clipboard) NULL(default)       0
  513. //  Drag/Drop       TRUE/FALSE  X               X                   0
  514. //  PasteLink       TRUE        NULL(clipboard) NULL(default)       0
  515. //  PasteSpecial    TRUE/FALSE  X               NULL(default)       X
  516. CRectItem* CMainView::DoPasteItem(BOOL bLink, COleDataObject* pDataObject,
  517.     CPoint* pPoint, CLIPFORMAT cfFormat)
  518. {
  519.     BeginWaitCursor();
  520.  
  521.     CRectItem* pItem = GetDocument()->CreateItem();
  522.     ASSERT_VALID(pItem);
  523.     BOOL bAllowAdjust = (pPoint == NULL) ? TRUE : FALSE;
  524.  
  525.     // use clipboard data if not doing drag/drop
  526.     COleDataObject clipboardData;
  527.     if (pDataObject == NULL)
  528.     {
  529.         clipboardData.AttachClipboard();
  530.         pDataObject = &clipboardData;
  531.     }
  532.  
  533.     TRY
  534.     {
  535.         if (cfFormat == CMainDoc::m_cfPrivate)
  536.         {
  537.             // if format specified (i.e. PasteSpecial) then use that one
  538.             DoPasteNative(pDataObject, pPoint, pItem);
  539.         }
  540.         else if (!bLink && cfFormat == 0 &&
  541.             pDataObject->IsDataAvailable(CMainDoc::m_cfPrivate))
  542.         {
  543.             // if we're not pasting a link, cfFormat was unspecified,
  544.             // and private format is available use it
  545.             DoPasteNative(pDataObject, pPoint, pItem);
  546.         }
  547.         // otherwise perform a standard paste
  548.         else if (bAllowAdjust)
  549.         {
  550.             CPoint ptDef(10, -10);
  551.             DoPasteStandard(bLink, pDataObject, &ptDef, pItem, cfFormat);
  552.         }
  553.         else
  554.         {
  555.             DoPasteStandard(bLink, pDataObject, pPoint, pItem, cfFormat);
  556.         }
  557.  
  558.         if (bAllowAdjust)
  559.         {
  560.             // allow document to adjust position of item so that it doesn't
  561.             // lay directly over an item of the same size
  562.             // this only occurs if the drop point is not specified
  563.             GetDocument()->AdjustItemPosition(pItem);
  564.         }
  565.     }
  566.     CATCH_ALL(e)
  567.     {
  568.         // general cleanup
  569.         TRACE0("failed to embed/link an OLE object\n");
  570.         pItem->Delete();
  571.         pItem = NULL;
  572.     }
  573.     END_CATCH_ALL
  574.  
  575.     // set the selection with bSafeSelect = TRUE
  576.     SetSelection(pItem, TRUE);
  577.  
  578.     // update the document and views
  579.     GetDocument()->SetModifiedFlag();
  580.     GetDocument()->UpdateAllViews(NULL, 0, pItem);      // including this view
  581.  
  582.     EndWaitCursor();
  583.  
  584.     return pItem;
  585. }
  586.  
  587. /////////////////////////////////////////////////////////////////////////////
  588. // Insert New Object and Activate Object
  589.  
  590. void CMainView::OnInsertObject()
  591. {
  592.     COleInsertDialog dlg;
  593.     if (dlg.DoModal() != IDOK)
  594.         return;
  595.  
  596.     BeginWaitCursor();
  597.  
  598.     CRectItem* pItem = NULL;
  599.     TRY
  600.     {
  601.         // create item from dialog results
  602.         pItem = GetDocument()->CreateItem();
  603.         if (!dlg.CreateItem(pItem))
  604.             AfxThrowMemoryException();  // any exception will do
  605.  
  606.         // try to get initial presentation data
  607.         pItem->UpdateLink();
  608.         pItem->UpdateExtent();
  609.  
  610.         // if insert new object -- initially show the object
  611.         if (dlg.GetSelectionType() == COleInsertDialog::createNewItem)
  612.             pItem->DoVerb(OLEIVERB_SHOW, this);
  613.  
  614.         SetSelection(pItem);
  615.     }
  616.     CATCH_ALL(e)
  617.     {
  618.         // cleanup item, if allocated
  619.         if (pItem != NULL)
  620.             GetDocument()->DeleteItem(pItem);
  621.  
  622.         AfxMessageBox(IDP_FAILED_TO_CREATE);
  623.     }
  624.     END_CATCH_ALL
  625.  
  626.     EndWaitCursor();
  627. }
  628.  
  629. void CMainView::OnLButtonDblClk(UINT, CPoint)
  630. {
  631.     // Double click will activate the main verb
  632.     if (m_pSelection != NULL)
  633.     {
  634.         BeginWaitCursor();
  635.         LONG iVerb = OLEIVERB_PRIMARY;
  636. #ifndef _MAC        
  637.         if (GetKeyState(VK_CONTROL) < 0)
  638. #else
  639.         if (GetKeyState(VK_OPTION) < 0)
  640. #endif            
  641.             iVerb = OLEIVERB_OPEN;
  642.         m_pSelection->DoVerb(iVerb, this);
  643.         EndWaitCursor();
  644.     }
  645. }
  646.  
  647. /////////////////////////////////////////////////////////////////////////////
  648. // Hit detection, moving and resizing items
  649.  
  650. CRectItem* CMainView::GetHitItem(CPoint point)
  651. {
  652.     CMainDoc* pDoc = GetDocument();
  653.     CRectItem* pItemHit = NULL;
  654.  
  655.     // Find the item hit by the mouse
  656.     POSITION pos = pDoc->GetStartPosition();
  657.     while (pos != NULL)
  658.     {
  659.         CRectItem* pItem = DYNAMIC_DOWNCAST(CRectItem, pDoc->GetNextItem(pos));
  660.         if (pItem != NULL)
  661.         {
  662.             CRectTracker tracker;
  663.             SetupTracker(&tracker, pItem);
  664.             if (tracker.HitTest(point) >= 0)
  665.             {
  666.                 pItemHit = pItem;
  667.                 // items later in the list are drawn on top - so keep looking
  668.             }
  669.         }
  670.     }
  671.     return pItemHit;
  672. }
  673.  
  674. void CMainView::DocToClient(CRect& rect)
  675. {
  676.     CClientDC dc(this);
  677.     OnPrepareDC(&dc);
  678.     dc.LPtoDP(&rect); // convert logical rect to device rect
  679.     rect.NormalizeRect();
  680. }
  681.  
  682. void CMainView::ClientToDoc(CRect& rect)
  683. {
  684.     CClientDC dc(this);
  685.     OnPrepareDC(&dc);
  686.     dc.DPtoLP(&rect); // convert device rect to logical rect
  687. }
  688.  
  689. void CMainView::DocToClient(CSize& size)
  690. {
  691.     CClientDC dc(this);
  692.     OnPrepareDC(&dc);
  693.     dc.LPtoDP(&size); // convert logical size to device size
  694.     size.cx = abs(size.cx);
  695.     size.cy = abs(size.cy);
  696. }
  697.  
  698. void CMainView::ClientToDoc(CSize& size)
  699. {
  700.     CClientDC dc(this);
  701.     OnPrepareDC(&dc);
  702.     dc.DPtoLP(&size); // convert device rect to logical rect
  703.     size.cx = abs(size.cx);
  704.     size.cy = abs(size.cy);
  705. }
  706.  
  707. void CMainView::DocToClient(CPoint& point)
  708. {
  709.     CClientDC dc(this);
  710.     OnPrepareDC(&dc);
  711.     dc.LPtoDP(&point); // convert logical point to device point
  712. }
  713.  
  714. void CMainView::ClientToDoc(CPoint& point)
  715. {
  716.     CClientDC dc(this);
  717.     OnPrepareDC(&dc);
  718.     dc.DPtoLP(&point); // convert device point to logical point
  719. }
  720.  
  721. void CMainView::OnLButtonDown(UINT /*nFlags*/, CPoint point)
  722. {
  723.     CRectItem* pItemHit = GetHitItem(point);
  724.     SetSelection(pItemHit);
  725.     if (pItemHit == NULL)
  726.         return;
  727.  
  728.     CRect rectLimit;
  729.     GetClientRect(rectLimit);
  730.  
  731.     CRectTracker tracker;
  732.     SetupTracker(&tracker, pItemHit);
  733.  
  734.     UpdateWindow(); // update before entering the tracker
  735.     if (tracker.HitTest(point) == CRectTracker::hitMiddle) // moving, not sizing
  736.     {
  737.         // determine mouse position offset from the item itself
  738.         CRect rect = pItemHit->GetRect();
  739.         DocToClient(rect);
  740.         CPoint ptOffset(point.x - rect.left, point.y - rect.top);
  741.  
  742.         // determine sensitivity rectangle (determines when drag starts)
  743.         CRect rectDrag(rect.left, rect.top, rect.left+1, rect.top+1);
  744.  
  745.         // execute the drag/drop operation
  746.         m_bInDrag = TRUE;
  747.         ClientToScreen(&rect);  // must be in screen co-ordinates
  748.         ClientToScreen(&rectDrag);
  749.         DROPEFFECT dropEffect = pItemHit->DoDragDrop(rect, ptOffset,
  750.             TRUE, DROPEFFECT_COPY|DROPEFFECT_MOVE, &rectDrag);
  751.         if (m_bInDrag == FALSE) // move in same window
  752.             return;
  753.         m_bInDrag = FALSE;
  754.  
  755.         if (dropEffect == DROPEFFECT_MOVE)
  756.         {
  757.             // the item was moved (essentially a copy w/delete)
  758.             pItemHit->Invalidate();
  759.             if (m_pSelection == pItemHit)
  760.                 m_pSelection = NULL;
  761.             GetDocument()->DeleteItem(pItemHit);
  762.         }
  763.     }
  764.     else if (tracker.Track(this, point))
  765.     {
  766.         ClientToDoc(tracker.m_rect);
  767.         pItemHit->Move(tracker.m_rect);
  768.         GetDocument()->SetModifiedFlag();
  769.     }
  770. }
  771.  
  772. BOOL CMainView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
  773. {
  774.     if (pWnd == this && m_pSelection != NULL)
  775.     {
  776.         // give the tracker for the selection a chance
  777.         CRectTracker tracker;
  778.         SetupTracker(&tracker, m_pSelection);
  779.         if (tracker.SetCursor(this, nHitTest))
  780.             return TRUE;
  781.     }
  782.     return CScrollView::OnSetCursor(pWnd, nHitTest, message);
  783. }
  784.  
  785. /////////////////////////////////////////////////////////////////////////////
  786. // Right mouse for popup context sensitive menu
  787.  
  788. void CMainView::OnRButtonDown(UINT, CPoint point)
  789. {
  790.     // make sure window is active
  791.     GetParentFrame()->ActivateFrame();
  792.  
  793.     SetSelection(GetHitItem(point));    // reselect item if appropriate
  794.     UpdateWindow();
  795.  
  796.     if (m_pSelection != NULL)
  797.     {
  798.         CMenu bar;
  799.         if (bar.LoadMenu(ID_OBJECT_POPUP_MENU))
  800.         {
  801.             CMenu& popup = *bar.GetSubMenu(0);
  802.             ASSERT(popup.m_hMenu != NULL);
  803.  
  804.             ClientToScreen(&point);
  805.             popup.TrackPopupMenu(TPM_RIGHTBUTTON,
  806.                 point.x, point.y,
  807.                 AfxGetMainWnd()); // route commands through main window
  808.         }
  809.     }
  810. }
  811.  
  812. void CMainView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
  813. {
  814.     MessageBeep(0);     // to test for proper focus transfer
  815.  
  816.     CScrollView::OnChar(nChar, nRepCnt, nFlags);
  817. }
  818.  
  819. void CMainView::OnSetFocus(CWnd* pOldWnd)
  820. {
  821.     COleClientItem* pActiveItem = GetDocument()->GetInPlaceActiveItem(this);
  822.     if (pActiveItem != NULL &&
  823.         pActiveItem->GetItemState() == COleClientItem::activeUIState)
  824.     {
  825.         // need to set focus to this item if it is in the same view
  826.         CWnd* pWnd = pActiveItem->GetInPlaceWindow();
  827.         if (pWnd != NULL)
  828.         {
  829.             pWnd->SetFocus();
  830.             return;
  831.         }
  832.     }
  833.  
  834.     CScrollView::OnSetFocus(pOldWnd);
  835. }
  836.  
  837. void CMainView::OnSize(UINT nType, int cx, int cy)
  838. {
  839.     CScrollView::OnSize(nType, cx, cy);
  840.  
  841.     UpdateActiveItem();
  842. }
  843.  
  844. /////////////////////////////////////////////////////////////////////////////
  845. // support for drag/drop
  846.  
  847. int CMainView::OnCreate(LPCREATESTRUCT lpCreateStruct)
  848. {
  849.     if (CScrollView::OnCreate(lpCreateStruct) == -1)
  850.         return -1;
  851.  
  852.     // register drop target
  853.     m_dropTarget.Register(this);
  854.  
  855.     return 0;
  856. }
  857.  
  858. BOOL CMainView::OnDrop(COleDataObject* pDataObject,
  859.     DROPEFFECT dropEffect, CPoint point)
  860. {
  861.     ASSERT_VALID(this);
  862.  
  863.     // clean up focus rect
  864.     OnDragLeave();
  865.  
  866.     // offset point as appropriate for dragging
  867.     GetObjectInfo(pDataObject, &m_dragSize, &m_dragOffset);
  868.     CClientDC dc(NULL);
  869. #ifndef _MAC
  870.     dc.HIMETRICtoDP(&m_dragSize);
  871.     dc.HIMETRICtoDP(&m_dragOffset);
  872. #endif
  873.     point -= m_dragOffset;
  874.  
  875.     // if move within the view
  876.     ClientToDoc(point);
  877.     if ((dropEffect & DROPEFFECT_MOVE) && m_bInDrag)
  878.     {
  879.         ASSERT(m_pSelection != NULL);
  880.         m_bInDrag = FALSE; // signal drag code that a move happened
  881.         // set top-left based on point of drop
  882.         CRect rect = m_pSelection->GetRect();
  883.         if (rect.TopLeft() != point) // if moved
  884.         {
  885.             m_pSelection->Move(CRect(point,rect.Size()));
  886.             GetDocument()->SetModifiedFlag();
  887.         }
  888.     }
  889.     // check and paste link
  890.     else if ((dropEffect & DROPEFFECT_LINK) && DoPasteItem(TRUE, pDataObject, &point))
  891.         return TRUE;
  892.  
  893.     // paste embedding/static
  894.     else if (DoPasteItem(FALSE, pDataObject, &point))
  895.         return TRUE;
  896.  
  897.     return FALSE;
  898. }
  899.  
  900. BOOL CMainView::GetObjectInfo(COleDataObject* pDataObject,
  901.     CSize* pSize, CSize* pOffset)
  902. {
  903.     ASSERT(pSize != NULL);
  904.  
  905.     // get object descriptor data
  906.     HGLOBAL hObjDesc = pDataObject->GetGlobalData(m_cfObjectDescriptor);
  907.     if (hObjDesc == NULL)
  908.     {
  909.         if (pOffset != NULL)
  910.             *pOffset = CSize(0, 0); // fill in defaults instead
  911.         *pSize = CSize(0, 0);
  912.         return FALSE;
  913.     }
  914.     ASSERT(hObjDesc != NULL);
  915.  
  916.     // otherwise, got CF_OBJECTDESCRIPTOR ok.  Lock it down and extract size.
  917.     LPOBJECTDESCRIPTOR pObjDesc = (LPOBJECTDESCRIPTOR)GlobalLock(hObjDesc);
  918.     ASSERT(pObjDesc != NULL);
  919.     pSize->cx = (int)pObjDesc->sizel.cx;
  920.     pSize->cy = (int)pObjDesc->sizel.cy;
  921.     if (pOffset != NULL)
  922.     {
  923.         pOffset->cx = (int)pObjDesc->pointl.x;
  924.         pOffset->cy = (int)pObjDesc->pointl.y;
  925.     }
  926.     GlobalUnlock(hObjDesc);
  927.     GlobalFree(hObjDesc);
  928.  
  929.     // successfully retrieved pSize & pOffset info
  930.     return TRUE;
  931. }
  932.  
  933. DROPEFFECT CMainView::OnDragEnter(COleDataObject* pDataObject,
  934.     DWORD grfKeyState, CPoint point)
  935. {
  936.     ASSERT(m_prevDropEffect == DROPEFFECT_NONE);
  937.  
  938.     GetObjectInfo(pDataObject, &m_dragSize, &m_dragOffset);
  939.     CClientDC dc(NULL);
  940. #ifndef _MAC
  941.     dc.HIMETRICtoDP(&m_dragSize);
  942.     dc.HIMETRICtoDP(&m_dragOffset);
  943. #endif
  944.  
  945.     return OnDragOver(pDataObject, grfKeyState, point);
  946. }
  947.  
  948. DROPEFFECT CMainView::OnDragOver(COleDataObject*,
  949.     DWORD grfKeyState, CPoint point)
  950. {
  951.     point -= m_dragOffset;  // adjust target rect by original cursor offset
  952.  
  953.     // check for point outside logical area -- i.e. in hatched region
  954.     // GetTotalSize() returns the size passed to SetScrollSizes
  955.     CRect rectScroll(CPoint(0, 0), GetTotalSize());
  956.  
  957.     CRect rectItem(point,m_dragSize);
  958.     if (rectItem.IsRectEmpty())
  959.     {
  960.         // some apps might have a null size in the object descriptor...
  961.         rectItem.InflateRect(1,1);
  962.     }        
  963.     rectItem.OffsetRect(GetDeviceScrollPosition());
  964.  
  965.     DROPEFFECT de = DROPEFFECT_NONE;
  966.     CRect rectTemp;
  967.     if (rectTemp.IntersectRect(rectScroll, rectItem))
  968.     {
  969.         // check for force link
  970. #ifndef _MAC
  971.         if ((grfKeyState & (MK_CONTROL|MK_SHIFT)) == (MK_CONTROL|MK_SHIFT))
  972. #else
  973.         if ((grfKeyState & (MK_OPTION|MK_SHIFT)) == (MK_OPTION|MK_SHIFT))
  974. #endif         
  975.             de = DROPEFFECT_LINK;
  976.         // check for force copy
  977. #ifndef _MAC        
  978.         else if ((grfKeyState & MK_CONTROL) == MK_CONTROL)
  979. #else
  980.         else if ((grfKeyState & MK_OPTION) == MK_OPTION)
  981. #endif        
  982.             de = DROPEFFECT_COPY;
  983.         // check for force move
  984.         else if ((grfKeyState & MK_ALT) == MK_ALT)
  985.             de = DROPEFFECT_MOVE;
  986.         // default -- recommended action is move
  987.         else
  988.             de = DROPEFFECT_MOVE;
  989.     }
  990.  
  991.     if (point == m_dragPoint)
  992.         return de;
  993.  
  994.     // otherwise, cursor has moved -- need to update the drag feedback
  995.     CClientDC dc(this);
  996.     if (m_prevDropEffect != DROPEFFECT_NONE)
  997.     {
  998.         // erase previous focus rect
  999.         dc.DrawFocusRect(CRect(m_dragPoint, m_dragSize));
  1000.     }
  1001.     m_prevDropEffect = de;
  1002.     if (m_prevDropEffect != DROPEFFECT_NONE)
  1003.     {
  1004.         m_dragPoint = point;
  1005.         dc.DrawFocusRect(CRect(point, m_dragSize));
  1006.     }
  1007.     return de;
  1008. }
  1009.  
  1010. void CMainView::OnDragLeave()
  1011. {
  1012.     CClientDC dc(this);
  1013.     if (m_prevDropEffect != DROPEFFECT_NONE)
  1014.     {
  1015.         dc.DrawFocusRect(CRect(m_dragPoint,m_dragSize)); // erase previous focus rect
  1016.         m_prevDropEffect = DROPEFFECT_NONE;
  1017.     }
  1018. }
  1019.  
  1020. /////////////////////////////////////////////////////////////////////////////
  1021. // Commands for switching display aspects
  1022.  
  1023. void CMainView::OnObjectDisplayContent()
  1024. {
  1025.     if (m_pSelection == NULL)
  1026.         return;
  1027.     ASSERT_VALID(m_pSelection);
  1028.     m_pSelection->Invalidate();
  1029.     m_pSelection->SetDrawAspect(DVASPECT_CONTENT);
  1030.     m_pSelection->UpdateExtent();
  1031.     m_pSelection->Invalidate();
  1032. }
  1033.  
  1034. void CMainView::OnUpdateObjectDisplayContent(CCmdUI* pCmdUI)
  1035. {
  1036.     if (m_pSelection == NULL)
  1037.     {
  1038.         pCmdUI->Enable(FALSE);
  1039.         return;
  1040.     }
  1041.     ASSERT_VALID(m_pSelection);
  1042.     pCmdUI->SetCheck(m_pSelection->GetDrawAspect() == DVASPECT_CONTENT);
  1043.     pCmdUI->Enable(TRUE);
  1044. }
  1045.  
  1046. void CMainView::OnObjectDisplayAsIcon()
  1047. {
  1048.     if (m_pSelection == NULL)
  1049.         return;
  1050.     ASSERT_VALID(m_pSelection);
  1051.     m_pSelection->Invalidate();
  1052.     m_pSelection->SetDrawAspect(DVASPECT_ICON);
  1053.     m_pSelection->UpdateExtent();
  1054.     m_pSelection->Invalidate();
  1055. }
  1056.  
  1057. void CMainView::OnUpdateObjectDisplayAsIcon(CCmdUI* pCmdUI)
  1058. {
  1059.     if (m_pSelection == NULL)
  1060.     {
  1061.         pCmdUI->Enable(FALSE);
  1062.         return;
  1063.     }
  1064.     ASSERT_VALID(m_pSelection);
  1065.     pCmdUI->SetCheck(m_pSelection->GetDrawAspect() == DVASPECT_ICON);
  1066.     pCmdUI->Enable(TRUE);
  1067. }
  1068.  
  1069. void CMainView::UpdateActiveItem()
  1070. {
  1071.     // when there is an active item visible, sizing the window may cause
  1072.     //  more/less of the in-place object to become visible.
  1073.     //  (ie. the clipping rectangle changes with the size of the window)
  1074.     // a container supporting scrolling would also have to do this
  1075.     //  when scrolling the contents of the window.
  1076.  
  1077.     COleClientItem* pActiveItem = GetDocument()->GetInPlaceActiveItem(this);
  1078.     if (pActiveItem != NULL &&
  1079.         pActiveItem->GetItemState() == COleClientItem::activeUIState &&
  1080.         pActiveItem->GetActiveView() == this)
  1081.     {
  1082.         // this will update the item rectangles by calling
  1083.         //  OnGetPosRect & OnGetClipRect.
  1084.         pActiveItem->SetItemRects();
  1085.     }
  1086. }
  1087.  
  1088. void CMainView::OnUpdateEditClone(CCmdUI* pCmdUI)
  1089. {
  1090.     pCmdUI->Enable(m_pSelection != NULL);
  1091. }
  1092.  
  1093. void CMainView::OnEditClone()
  1094. {
  1095.     if (m_pSelection == NULL)
  1096.         return;
  1097.  
  1098.     BeginWaitCursor();
  1099.  
  1100.     CRectItem* pItem = NULL;
  1101.     TRY
  1102.     {
  1103.         // create item from dialog results
  1104.         pItem = GetDocument()->CreateItem();
  1105.         if (!pItem->CreateCloneFrom(m_pSelection))
  1106.             AfxThrowMemoryException();  // any exception will do
  1107.  
  1108.         // offset it so we can see the clone easier
  1109.         CRect rect(20, 20, 0, 0);
  1110.         ClientToDoc(rect);
  1111.         pItem->m_ptPos.x += rect.left;
  1112.         pItem->m_ptPos.y += rect.top;
  1113.         ASSERT_VALID(pItem);
  1114.     }
  1115.     CATCH_ALL(e)
  1116.     {
  1117.         // cleanup item, if allocated
  1118.         if (pItem != NULL)
  1119.             GetDocument()->DeleteItem(pItem);
  1120.  
  1121.         AfxMessageBox(IDP_FAILED_TO_CREATE);
  1122.     }
  1123.     END_CATCH_ALL
  1124.  
  1125.     EndWaitCursor();
  1126. }
  1127.  
  1128. void CMainView::OnPasteSpecial()
  1129. {
  1130.     COlePasteSpecialDialog dlg;
  1131.     dlg.AddFormat(CMainDoc::m_cfPrivate, TYMED_HGLOBAL,
  1132.         IDS_PRIVATE_CF_DESCR, FALSE, FALSE);
  1133.     dlg.AddStandardFormats();
  1134.     if (dlg.DoModal() != IDOK)
  1135.         return;
  1136.  
  1137.     CRectItem* pItem = NULL;
  1138.     TRY
  1139.     {
  1140.         // Get the clipboard format of the selected
  1141.         CLIPFORMAT cf = dlg.m_ps.arrPasteEntries[dlg.m_ps.nSelectedIndex].fmtetc.cfFormat;
  1142.         if (cf == CMainDoc::m_cfPrivate)
  1143.         {
  1144.             BOOL bLink = dlg.GetSelectionType() ==
  1145.                 COlePasteSpecialDialog::pasteLink;
  1146.             COleDataObject dataObject;
  1147.             dataObject.Attach(dlg.m_ps.lpSrcDataObj, FALSE);
  1148.             pItem = DoPasteItem(bLink, &dataObject, NULL, cf);
  1149.  
  1150.             // try to get initial presentation data
  1151.             pItem->UpdateLink();
  1152.         }
  1153.         else
  1154.         {
  1155.             pItem = GetDocument()->CreateItem();
  1156.             if (!dlg.CreateItem(pItem))
  1157.             {
  1158.                 TRACE0("Warning: paste special failed to create item.\n");
  1159.                 AfxThrowMemoryException();
  1160.             }
  1161.  
  1162.             // try to get initial presentation data
  1163.             pItem->UpdateLink();
  1164.  
  1165.             // try to get initial extent
  1166.             pItem->UpdateExtent();
  1167.  
  1168.             // allow document to offset item to avoid direct superimposition
  1169.             GetDocument()->AdjustItemPosition(pItem);
  1170.  
  1171.             // set the selection with bSafeSelect = TRUE
  1172.             SetSelection(pItem, TRUE);
  1173.             GetDocument()->SetModifiedFlag();
  1174.             GetDocument()->UpdateAllViews(NULL, 0, pItem);
  1175.         }
  1176.     }
  1177.     CATCH_ALL(e)
  1178.     {
  1179.         // cleanup item, if allocated
  1180.         if (pItem != NULL)
  1181.             GetDocument()->DeleteItem(pItem);
  1182.         AfxMessageBox(IDP_FAILED_TO_CREATE);
  1183.         return;
  1184.     }
  1185.     END_CATCH_ALL
  1186. }
  1187.  
  1188. void CMainView::OnUpdateEditPaste(CCmdUI* pCmdUI)
  1189. {
  1190.     // determine if private or standard OLE formats are on the clipboard
  1191.     COleDataObject dataObj;
  1192.     BOOL bEnable = dataObj.AttachClipboard() &&
  1193.         (dataObj.IsDataAvailable(CMainDoc::m_cfPrivate) ||
  1194.          COleClientItem::CanCreateFromData(&dataObj));
  1195.  
  1196.     // enable command based on availability
  1197.     pCmdUI->Enable(bEnable);
  1198. }
  1199.  
  1200. void CMainView::OnObjectResetsize()
  1201. {
  1202.     ASSERT(m_pSelection != NULL);
  1203.     m_pSelection->ResetSize();
  1204. }
  1205.  
  1206. void CMainView::OnCancelInplace()
  1207. {
  1208.     // deactivate the inplace active item on this frame/view
  1209.     COleClientItem* pActiveItem = GetDocument()->GetInPlaceActiveItem(this);
  1210.     if (pActiveItem != NULL)
  1211.         pActiveItem->Deactivate();
  1212.     ASSERT(GetDocument()->GetInPlaceActiveItem(this) == NULL);
  1213. }
  1214.  
  1215. void CMainView::OnDestroy()
  1216. {
  1217.     CScrollView::OnDestroy();
  1218.  
  1219.     // deactivate the inplace active item on this view
  1220.     COleClientItem* pActiveItem = GetDocument()->GetInPlaceActiveItem(this);
  1221.     if (pActiveItem != NULL && pActiveItem->GetActiveView() == this)
  1222.     {
  1223.         pActiveItem->Deactivate();
  1224.         ASSERT(GetDocument()->GetInPlaceActiveItem(this) == NULL);
  1225.     }
  1226. }
  1227.  
  1228. void CMainView::OnUpdateOleEditProperties(CCmdUI* pCmdUI) 
  1229. {
  1230.     pCmdUI->Enable(m_pSelection != NULL);
  1231. }
  1232.  
  1233. // edit properties dialog specific to OCLIENT
  1234. class COlePropertiesEx : public COlePropertiesDialog
  1235. {
  1236. public:
  1237.     COlePropertiesEx(COleClientItem* pItem,
  1238.         UINT nScaleMin = 10, UINT nScaleMax = 500, CWnd* pParentWnd = NULL)
  1239.         : COlePropertiesDialog(pItem, nScaleMin, nScaleMax, pParentWnd)
  1240.         { }
  1241.  
  1242.     virtual BOOL OnApplyScale(
  1243.         COleClientItem* pItem, int nCurrentScale, BOOL bRelativeToOrig);
  1244. };
  1245.  
  1246. BOOL COlePropertiesEx::OnApplyScale(
  1247.     COleClientItem* pItem, int nCurrentScale, BOOL bRelativeToOrig)
  1248. {
  1249.     if (nCurrentScale != -1)
  1250.     {
  1251.         ASSERT_VALID(pItem);
  1252.         CRectItem* pRectItem = (CRectItem*)pItem;
  1253.         ASSERT_KINDOF(CRectItem, pRectItem);
  1254.  
  1255.         // reset to original size if necessary
  1256.         if (bRelativeToOrig)
  1257.             pRectItem->ResetSize();
  1258.  
  1259.         // update extent to reflect scaling factor
  1260.         pRectItem->Invalidate();
  1261.         CSize size = pRectItem->GetSize();
  1262.         size.cx = MulDiv(size.cx, nCurrentScale, 100);
  1263.         size.cy = MulDiv(size.cy, nCurrentScale, 100);
  1264.         pRectItem->SetSize(size);
  1265.         pRectItem->Invalidate();
  1266.     }
  1267.     return TRUE;
  1268. }
  1269.  
  1270. void CMainView::OnOleEditProperties() 
  1271. {
  1272.     ASSERT(m_pSelection != NULL);
  1273.  
  1274.     COlePropertiesEx dlg(m_pSelection);
  1275.     dlg.DoModal();
  1276. }
  1277.  
  1278. void CMainView::OnUpdateOleChangeSource(CCmdUI* pCmdUI) 
  1279. {
  1280.     pCmdUI->Enable(m_pSelection != NULL && m_pSelection->GetType() == OT_LINK);
  1281. }
  1282.  
  1283. void CMainView::OnOleChangeSource() 
  1284. {
  1285.     ASSERT(m_pSelection != NULL && m_pSelection->GetType() == OT_LINK);
  1286.  
  1287.     COleChangeSourceDialog dlg(m_pSelection);
  1288.     dlg.DoModal();
  1289. }
  1290.